package com.reverse.engineering.util.core.run.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.HashMap;
import java.util.stream.Stream;

import com.ApplicationProperties;
import com.reverse.engineering.util.core.run.bean.DatabaseProperties;
import com.reverse.engineering.util.core.run.bean.FileMessage;
import com.reverse.engineering.util.core.run.bean.TemplateMessage;
import com.reverse.engineering.util.core.run.bean.Templates;

/**
 * 文件工具类
 * 
 * @author liu
 * @Date 2020-06-15 14:45:33
 * @Description
 *
 */
public class FileUtils {

    public static final String thisFilePath = new File("").getAbsolutePath();
    public static final String thisPath = thisFilePath + "/";
    public static final String thisJavaPath = thisPath + "src/main/java/";
    public static final String thisResourcesPath = thisPath + "src/main/resources/";
    /**模板文件的路径*/
    public static final String templatePath = "template/";
    /**模板文件的基础路径*/
    public static final String templateBasePath =
        FileUtils.thisResourcesPath + templatePath + DatabaseProperties.DATABASE_TYPE.getTemplateRootPath();
    /**模板路径在Map中的Key*/
    public static final String templatePathKey = "templatePathKey";
    /**模板名在Map中的Key*/
    public static final String templateNameKey = "templateNameKey";

    /**
     * 通过基础路径递归获取模板路径
     * 
     * @return
     * @throws IOException
     */
    public static void initTemplatePathsByBasePath() throws IOException {
        initTemplatePathsByBasePath(new File(templateBasePath));
    }

    /**
     * 递归获取模板路径
     * 
     * @return
     * @throws IOException
     */
    public static void initTemplatePathsByBasePath(File file) throws IOException {
        HashMap<String, TemplateMessage> template = Templates.template;
        if (file.isFile()) {
            String absolutePath = file.getAbsolutePath();
            String name = "";
            TemplateMessage templateMessage = new TemplateMessage();
            String substring = absolutePath.substring(templateBasePath.length() + 1);
            substring = substring.replace("\\", "/");
            String[] split = substring.split("/");
            name += InitProperties.toLowerCase(split[0]);
            for (int i = 1; i < split.length; i++) {
                name += InitProperties.toUpperCase(split[i]);
            }
            templateMessage.setPath(substring);
            template.put(name, templateMessage);
        } else if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                initTemplatePathsByBasePath(f);
            }
        }
    }

    /**
     * 根据文件路径读取文件的每一行,拼接成一个字符串
     * 
     * @param pathname
     * @return
     * @throws IOException 
     */
    @SuppressWarnings("resource")
    public static String getContentByPath(String pathname) throws IOException {
        FileReader fileReader = new FileReader(templateBasePath + "/" + pathname);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        Stream<String> lines = bufferedReader.lines();
        Object[] array = lines.toArray();
        if (array.length < 1) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (Object object : array) {
            stringBuilder.append("\n").append(object);
        }
        closeStream(bufferedReader);
        closeStream(fileReader);
        return stringBuilder.substring(1);
    }

    /**
     * 通过文件对象创建文件
     * 
     * @param pathname
     * @return
     * @throws IOException 
     */
    public static void createFileByString(FileMessage fileMessage) throws IOException {
        String filePath = getFilePath(fileMessage);
        File file = new File(filePath + fileMessage.getFileName() + fileMessage.getFileSuffix());
        deleteFileByFile(file);
        makeDirectoryByPathname(filePath);
        createNewFileByFile(file);
        FileWriter fileWriter = new FileWriter(file);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        bufferedWriter.write(fileMessage.getContent());
        closeStream(bufferedWriter);
        closeStream(fileWriter);
    }

    public static String getFilePath(FileMessage fileMessage) {
        StringBuilder stringBuilder = new StringBuilder();
        String filePath = fileMessage.getFilePath();
        if (filePath.length() == 0) {
            return filePath;
        } else if (filePath.startsWith(ApplicationProperties.classPath)) {
            stringBuilder.append(thisResourcesPath);
            filePath = filePath.substring(ApplicationProperties.classPath.length());
        } else if (!filePath.contains(":/")) {
            stringBuilder.append(thisJavaPath);
        }
        stringBuilder.append(filePath).append("/");
        return stringBuilder.toString();
    }

    public static void main(String[] args) throws IOException {
        File file = new File("com.sojson.dao");
        System.out.println(file.getAbsolutePath());
    }

    /**
     * 判断文件是否存在，不存在则创建
     * 
     * @param file File文件对象
     * @throws IOException
     */
    public static void createNewFileByFile(File file) throws IOException {
        if (!file.exists()) {
            file.createNewFile();
        }
    }

    /**
     * 判断文件是否存在，不存在则创建
     * 
     * @param pathname 文件路径
     * @throws IOException
     */
    public static void createNewFileByPathname(String pathname) throws IOException {
        File file = new File(pathname);
        if (!file.exists()) {
            file.createNewFile();
        }
    }

    /**
     * 判断目录是否存在，不存在则创建
     * 
     * @param file File文件对象
     */
    public static void makeDirectoryByFile(File file) {
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 判断目录是否存在，不存在则创建
     * 
     * @param pathname 文件路径
     */
    public static void makeDirectoryByPathname(String pathname) {
        File file = new File(pathname);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 判断文件是否存在，存在则删除
     * 
     * @param file File文件对象
     */
    // 因为File无法删除非空目录，所以需要先递归所有子文件
    public static void deleteFileByFile(File file) {
        // 判断文件是否存在
        if (file.exists()) {
            // 判断是文件还是目录
            if (file.isFile()) {
                // 是文件就删除
                file.delete();
            } else {
                // 是目录就递归调用此方法
                // 获取目录下的所有文件
                File[] listFiles = file.listFiles();
                for (File f : listFiles) {
                    deleteFileByFile(f);
                }
            }
        }
    }

    /**
     * 判断文件是否存在，存在则删除
     * 
     * @param pathname 文件路径
     */
    // 因为File无法删除非空目录，所以需要先递归所有子文件
    public static void deleteFileByPathname(String pathname) {
        File file = new File(pathname);
        // 判断文件是否存在
        if (file.exists()) {
            // 判断是文件还是目录
            if (file.isFile()) {
                // 是文件就删除
                file.delete();
            } else {
                // 是目录就递归调用此方法
                // 获取目录下的所有文件
                File[] listFiles = file.listFiles();
                for (File f : listFiles) {
                    deleteFileByFile(f);
                }
            }
        }
    }

    /**
     * 关闭字节输入流
     * 
     * @param inputStream 需要关闭的字节输入流
     * @throws IOException
     */
    public static void closeStream(InputStream inputStream) throws IOException {
        if (inputStream != null) {
            inputStream.close();
        }
    }

    /**
     * 关闭字节输出流
     * 
     * @param outputStream 需要关闭的字节输出流
     * @throws IOException
     */
    public static void closeStream(OutputStream outputStream) throws IOException {
        if (outputStream != null) {
            outputStream.close();
        }
    }

    /**
     * 关闭字符输入流
     * 
     * @param reader 需要关闭的字符输入流
     * @throws IOException
     */
    public static void closeStream(Reader reader) throws IOException {
        if (reader != null) {
            reader.close();
        }
    }

    /**
     * 关闭字符输出流
     * 
     * @param reader 需要关闭的字符输出流
     * @throws IOException
     */
    public static void closeStream(Writer writer) throws IOException {
        if (writer != null) {
            writer.close();
        }
    }

    /**
     * 关闭字节输入输出流
     * 
     * @param inputStream 需要关闭的字节输入流
     * @param outputStream 需要关闭的字节输出流
     * @throws IOException
     */
    public static void closeStream(InputStream inputStream, OutputStream outputStream) throws IOException {
        if (inputStream != null) {
            inputStream.close();
        }
        if (outputStream != null) {
            outputStream.close();
        }
    }

    /**
     * 关闭字符输入输出流
     * 
     * @param inputStream 需要关闭的字符输入流
     * @param outputStream 需要关闭的字符输出流
     * @throws IOException
     */
    public static void closeStream(Reader reader, Writer writer) throws IOException {
        if (reader != null) {
            reader.close();
        }
        if (writer != null) {
            writer.close();
        }
    }

}